#include "exp_http.h"


static znx_bool_t
znx_exp_http_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err);

static znx_bool_t znx_exp_http_conf_post();
static znx_bool_t znx_exp_http_main_init();
static znx_bool_t znx_exp_http_worker_init();
static znx_bool_t znx_exp_http_worker_proc_exit();
static znx_bool_t znx_exp_http_worker_exit();
static znx_bool_t znx_exp_http_main_exit();

static znx_bool_t znx_exp_http_site_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err);
static znx_bool_t znx_exp_http_addr_site_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err);
static znx_bool_t znx_exp_http_loc_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err);
static znx_bool_t znx_exp_http_site_conf_post(znx_http_site_conf_t *site_conf);

znx_http_module_t       exp_http_module = {
    0,
    ZNX_STRING("exp_http_module"),
    znx_exp_http_conf_parse,
    znx_exp_http_conf_post,
    znx_exp_http_site_conf_parse,
    znx_exp_http_addr_site_conf_parse,
    znx_exp_http_loc_conf_parse,
    znx_exp_http_site_conf_post,
    znx_exp_http_main_init,
    znx_exp_http_worker_init,
    znx_exp_http_worker_proc_exit,
    znx_exp_http_worker_exit,
    znx_exp_http_main_exit
};


static znx_command_t    exp_commands[] = {
    {
        ZNX_STRING("e1"),
        znx_command_set_int64,
        offsetof(znx_exp_http_conf_t, e1)
    },

    {
        ZNX_STRING("e2"),
        znx_command_set_string,
        offsetof(znx_exp_http_conf_t, e2)
    },

    {
        ZNX_STRING("e3"),
        znx_command_set_bool,
        offsetof(znx_exp_http_conf_t, e3)
    },

    znx_null_command
};


static znx_bool_t
znx_exp_http_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err)
{
    znx_exp_http_conf_t     *exp_conf;
    exp_conf = znx_pool_calloc(pool, sizeof(znx_exp_http_conf_t));
    exp_conf->e1 = ZNX_INT64_UNSET;
    exp_conf->e3 = ZNX_BOOL_UNSET;

    if (!znx_yaml_map_node_parser(exp_conf,
        pool, doc, root, exp_commands, err))
    {
        return ZNX_FALSE;
    }

    znx_http_set_main_module_conf(exp_http_module, exp_conf);

    return ZNX_TRUE;
}


static znx_bool_t
znx_exp_http_site_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err)
{
    znx_http_site_conf_t        *site_conf = conf;
    znx_exp_http_conf_t         *exp_conf;
    exp_conf = znx_pool_calloc(pool, sizeof(znx_exp_http_conf_t));
    exp_conf->e1 = ZNX_INT64_UNSET;
    exp_conf->e3 = ZNX_BOOL_UNSET;

    if (!znx_yaml_map_node_parser(exp_conf,
        pool, doc, root, exp_commands, err))
    {
        return ZNX_FALSE;
    }

    znx_http_set_site_module_conf(site_conf, exp_http_module, exp_conf);
    return ZNX_TRUE;
}


static znx_bool_t
znx_exp_http_addr_site_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err)
{
    znx_http_addr_site_conf_t       *addr_site = conf;
    znx_exp_http_conf_t             *exp_conf;
    exp_conf = znx_pool_calloc(pool, sizeof(znx_exp_http_conf_t));
    exp_conf->e1 = ZNX_INT64_UNSET;
    exp_conf->e3 = ZNX_BOOL_UNSET;

    if (!znx_yaml_map_node_parser(exp_conf,
        pool, doc, root, exp_commands, err))
    {
        return ZNX_FALSE;
    }

    znx_http_set_addr_site_module_conf(addr_site, exp_http_module, exp_conf);
    return ZNX_TRUE;
}


static znx_bool_t
znx_exp_http_loc_conf_parse(
    void *conf, znx_pool_t *pool, yaml_document_t *doc,
    yaml_node_t *root, znx_str_t *err)
{
    znx_http_loc_conf_t             *loc_conf = conf;
    znx_exp_http_conf_t             *exp_conf;
    exp_conf = znx_pool_calloc(pool, sizeof(znx_exp_http_conf_t));
    exp_conf->e1 = ZNX_INT64_UNSET;
    exp_conf->e3 = ZNX_BOOL_UNSET;

    if (!znx_yaml_map_node_parser(exp_conf,
        pool, doc, root, exp_commands, err))
    {
        return ZNX_FALSE;
    }

    znx_http_set_loc_module_conf(loc_conf, exp_http_module, exp_conf);
    return ZNX_TRUE;
}


static znx_bool_t
znx_exp_http_site_conf_post(znx_http_site_conf_t *site_conf)
{
    znx_exp_http_conf_t         *exp_http_conf;
    znx_exp_http_conf_t         *pre_exp_http_conf;

    pre_exp_http_conf = znx_http_get_main_module_conf(exp_http_module);
    exp_http_conf = znx_http_get_site_module_conf(site_conf, exp_http_module);
    if (exp_http_conf == NULL) {
        znx_http_set_site_module_conf(site_conf, exp_http_module, pre_exp_http_conf);
    } else {
        if (exp_http_conf->e1 == ZNX_INT64_UNSET) {
            exp_http_conf->e1 = pre_exp_http_conf->e1;
        }

        if (exp_http_conf->e2.len == 0) {
            exp_http_conf->e2 = pre_exp_http_conf->e2;
        }

        if (exp_http_conf->e3 == ZNX_BOOL_UNSET) {
            exp_http_conf->e3 = pre_exp_http_conf->e3;
        }
    }

    znx_http_addr_site_conf_t   *addr_site, *addr_sitep;
    pre_exp_http_conf = znx_http_get_site_module_conf(site_conf, exp_http_module);
    addr_sitep = site_conf->addr_sites->elts;
    for (size_t i = 0; i < site_conf->addr_sites->nelts; i++) {
        addr_site = addr_sitep + i;
        exp_http_conf = znx_http_get_addr_site_module_conf(addr_site, exp_http_module);
        if (exp_http_conf == NULL) {
            znx_http_set_addr_site_module_conf(addr_site, exp_http_module, pre_exp_http_conf);
        } else {
            if (exp_http_conf->e1 == ZNX_INT64_UNSET) {
                exp_http_conf->e1 = pre_exp_http_conf->e1;
            }

            if (exp_http_conf->e2.len == 0) {
                exp_http_conf->e2 = pre_exp_http_conf->e2;
            }

            if (exp_http_conf->e3 == ZNX_BOOL_UNSET) {
                exp_http_conf->e3 = pre_exp_http_conf->e3;
            }
        }

        znx_exp_http_conf_t     *pre;
        znx_http_loc_conf_t     *loc_conf, *loc_confp;
        pre = znx_http_get_addr_site_module_conf(addr_site, exp_http_module);
        loc_confp = addr_site->loc_confs->elts;
        for (size_t j = 0; j < addr_site->loc_confs->nelts; j++) {
            loc_conf = loc_confp + j;
            exp_http_conf = znx_http_get_loc_module_conf(loc_conf, exp_http_module);
            if (exp_http_conf == NULL) {
                znx_http_set_loc_module_conf(loc_conf, exp_http_module, pre);
            } else {
                if (exp_http_conf->e1 == ZNX_INT64_UNSET) {
                    exp_http_conf->e1 = pre->e1;
                }

                if (exp_http_conf->e2.len == 0) {
                    exp_http_conf->e2 = pre->e2;
                }

                if (exp_http_conf->e3 == ZNX_BOOL_UNSET) {
                    exp_http_conf->e3 = pre->e3;
                }
            }
        }
    }


    return ZNX_TRUE;
}


static znx_bool_t
znx_exp_http_conf_post()
{
    ZNX_DEF_LOG_DEBUG(NULL, "znx_exp_http_conf_post");
    return ZNX_TRUE;
}

static znx_bool_t
znx_exp_http_main_init()
{
    ZNX_DEF_LOG_DEBUG(NULL, "znx_exp_http_main_init");
    return ZNX_TRUE;
}

static znx_bool_t
znx_exp_http_worker_init()
{
    ZNX_DEF_LOG_DEBUG(NULL, "znx_exp_http_worker_init");
    return ZNX_TRUE;
}

static znx_bool_t
znx_exp_http_worker_proc_exit()
{
    ZNX_DEF_LOG_DEBUG(NULL, "znx_exp_http_worker_proc_exit");
    return ZNX_TRUE;
}

static znx_bool_t
znx_exp_http_worker_exit()
{
    ZNX_DEF_LOG_DEBUG(NULL, "znx_exp_http_worker_exit");
    return ZNX_TRUE;
}

static znx_bool_t
znx_exp_http_main_exit()
{
    ZNX_DEF_LOG_DEBUG(NULL, "znx_exp_http_main_exit");
    return ZNX_TRUE;
}